package com.sc.demo.plugins;

import java.util.Properties;

import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.log4j.Logger;

/**    
 *     
 * 项目名称：51credit-core-service    
 * 类名称：MasterSlaveXmlRouterPlugin    
 * 类描述：    读写分离路由（配合mysql Replication driver）仅限于 ibatis 方式  暂不支持 手动强制走主库
 * 创建人：huan    
 * 创建时间：2016年8月29日 下午5:03:41    
 * 修改人：huan    
 * 修改时间：2016年8月29日 下午5:03:41    
 * 修改备注：    
 * @version     
 *     
 */
@Intercepts({
	@Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
	@Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class})
})
public class MasterSlaveXmlRouterPlugin implements Interceptor {
	
    private static final String QUERY = "query";

	
	private Logger logger = Logger.getLogger(MasterSlaveXmlRouterPlugin.class);
	
    public Object intercept(Invocation invocation) throws Throwable {
		logger.debug("[MasterSlaveRouterPlugin] Method  = " + ((MappedStatement)invocation.getArgs()[0]).getId());
		String methodName = invocation.getMethod().getName();
		boolean isReadOnly = false;
		if( QUERY.equals(methodName)){
            isReadOnly = true;
        }
		//切换到从库
		((Executor)invocation.getTarget()).getTransaction().getConnection().setReadOnly(isReadOnly);
		Object o = invocation.proceed();
		//切换回主库，防止写操作失败
		((Executor)invocation.getTarget()).getTransaction().getConnection().setReadOnly(false);
		return o;
	}

	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}

	public void setProperties(Properties properties) {
	}
}
